#ifndef consola_main
#define consola_main 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <netinet/in.h>
#include "mtlib.c" //archivo con funciones para envio de mensajes
#include "leer_archivo_config.c" //leer datos desde un archivo de configuracion

//PROTOTIPOS FUNCIONES AUXILIARES
void ___descartar_linea_consola(void);
void ___procesar_mensaje_consola(mti_mensaje);
void ___cambiar_tamano (void ** ,unsigned int,  unsigned int);

//declaro variables globales
unsigned int descriptor;
unsigned char centro_consola = 0;
unsigned int descriptorAceptar;

int main (void) {

    char vectorComandos[7], dato; //inicializo vector que almacenara cadenas con comandos y/o path a archivo
    char * vectorCadenas = NULL;
    char * archivo;
    int i ,j, k, cantidad;
    int resultado, resultado2, pararEjecucion = 0;
    mti_mensaje datosMensaje;
    struct datos_config arch;
    int parar = 0;
    

    arch = ___leer_arch_config("path"); //obtengo el path desde el archivo de config

    archivo = arch.path; //le asigno el path para establecer comunicacion por AF_UNIX

        while (centro_consola == 0)
            centro_consola = mtf_obtener_descriptor(1024); //creo el centro de mensajes de la consola

        i = 0;

        for (k = 0; k <= 7; k ++)
        vectorComandos[k] = '\0';

        descriptor = mtf_conectar(centro_consola, MTP_UNIX_ESCUCHA, (char *) archivo); //me quedo escuchando por conexiones a la
        //consola,, traves de sockets unix,, por medio de un archivo
        
        //ACEPTO CONEXION CONSOLA CON SISTEMA FAT
        while (parar == 0) {
						
            if (mtf_recibir_mensajes(centro_consola) == 0) continue;

			mti_mensaje datosMensaje = mtf_siguiente_mensaje(centro_consola);

			if (datosMensaje.categoria != MTA_ACEPTAR) {
			continue;
			
			} else {
			parar = 1;
			descriptorAceptar = datosMensaje.remitente; //guardo el remitente para enviar los datos por el socket aceptado y no el de escucha
            }
		}

            if (descriptor == 0) {
                mtf_liberar_descriptor(centro_consola);
                return -EAGAIN;


            } else {

            printf(">>");
            dato = getchar(); //leo un caracter,, ingresado por teclado
            }

            while ( (i <= 7) && ((dato != '\n') && (dato != ' ')) ) { //mientras no sea linea nueva,, ni la cadena
            //ingresada sea superior a 7 caracteres ni sea un espacio en blanco
                vectorComandos[i] = dato; //ingreso los caracteres al vector
                dato = getchar();
                i++;
            }

            if (i > 7) {

                ___descartar_linea_consola();
                printf("Comando no valido \n");

            } else if (dato == '\n') {

                if  ( strcmp (vectorComandos, "fsinfo") == 0 )  { // comparo el vector para ver si coincide con el comando

                resultado = mtf_enviar_mensaje(centro_consola, descriptorAceptar, MTE_OBTENER_INFO_FS);
                //envio un mensaje al sistema fat para obtener los datos de la tabla fat

                    if (resultado == 0) {
                        mtf_desconectar(centro_consola, descriptor);
                        mtf_liberar_descriptor(centro_consola);
                        return -EAGAIN;

                    } else {

                        while (! (pararEjecucion)) {

                            while (! (mtf_recibir_mensajes(centro_consola)));

                            datosMensaje = mtf_siguiente_mensaje(centro_consola);
                            ___procesar_mensaje_consola(datosMensaje);
                            mtf_descartar_mensaje(centro_consola, datosMensaje.codigo);
                        }
                    }

                } else

                printf("Comando no valido \n");

            } else if ( strcmp (vectorComandos, "finfo") == 0 ) { //comparo el contenido del vector para ver si coincide
            //con el comando

                while ((dato = getchar()) == ' '); //mientras sea un espacio el caracter ingresado

                ungetc(dato, stdin);

                 cantidad = 1;
                ___cambiar_tamano( (void **) &vectorCadenas, sizeof(char), cantidad);
                vectorCadenas[0] = dato;

                    for (j = 1; ( (dato = getchar()) != '\n'); j ++) {

                        cantidad = cantidad + 1;
                        ___cambiar_tamano( (void **) &vectorCadenas, sizeof(char), cantidad);
                        vectorCadenas[j] = dato;
                    }

                resultado2 = mtf_enviar_mensaje(centro_consola, descriptorAceptar, MTE_OBTENER_INFO_ARCHIVO, (char *) vectorCadenas);
                //envio un mensaje al sistema fat para obtener los primeros 20 clusters del archivo

                free(vectorCadenas);

                    if (resultado2 == 0) {
                        mtf_desconectar(centro_consola, descriptor);
                        mtf_liberar_descriptor(centro_consola);
                        return -EAGAIN;

                    } else {
                        
                        pararEjecucion = 0;
                        while (! (pararEjecucion)) {

                            while(! (mtf_recibir_mensajes(centro_consola)));

                            datosMensaje = mtf_siguiente_mensaje(centro_consola);
                            ___procesar_mensaje_consola(datosMensaje);
                            mtf_descartar_mensaje(centro_consola, datosMensaje.codigo);
                        }
                    }

            } else
                printf("Comando no valido");

            mtf_desconectar(centro_consola, descriptor); //desconecto la conexion del centro de mensajes
            mtf_liberar_descriptor(centro_consola); //libero centro de mensajes con sus datos y conexiones
            return EXIT_SUCCESS;

}

void ___procesar_mensaje_consola(mti_mensaje datosMensaje) {


    switch(datosMensaje.categoria) {

    case MTA_ACEPTAR: //acepto una conexion

    break;

    case MTA_CERRAR: //se cerro la conexion

    break;

    case MTA_MENSAJE:

        switch (datosMensaje.tipo) {

        case MTE_NULL:

            mtf_enviar_mensaje(centro_consola, datosMensaje.remitente, MTR_NULL);

        break;

        case MTR_NULL:

        break;

        case MTQ_MENSAJE_NO_VALIDO:

        break;

        //mensajes para implementar consola_fat32
        case MTR_INFO_FS:
        {
        //declaro variables,, que utiliza el mensaje recibido,, como parametro a la funcion mtf_obtener_mensaje
            short tamanoSector;
            long tamanoFAT;
            long tamanoCluster;

                //obtengo datos del mensaje
                mtf_obtener_datos(centro_consola, datosMensaje.codigo,(short int *) &tamanoSector,
                                     (long int *) &tamanoCluster, (long int *) &tamanoFAT);

                printf("Tamano sector %d \n", tamanoSector);
                printf("Tamano cluster %ld \n", tamanoCluster);
                printf("Tamano FAT  %ld \n", tamanoFAT);
        }
        break;

        case MTR_NO_OBTUVO_INFO_FS: //no pudo obtener los datos del sistema fat
        {
            char motivo;

                mtf_obtener_datos(centro_consola, datosMensaje.codigo,(char *) &motivo);
        }
        break;

        case MTR_INFO_ARCHIVO: //recibo la info de los clusteres del archivo

        {
            uint32_t numerosClusteres[20];
            uint32_t * numeros = numerosClusteres;
            char posicion;
           
                mtf_obtener_datos(centro_consola, datosMensaje.codigo, NULL, (void **) &numeros);
            
                for (posicion = 0; posicion < 20; posicion ++) {
                
                unsigned long num = ntohl(numerosClusteres[posicion]); 
                
                    if (num == 0) {
                        break;
                        
                    } else {
                    	printf("#Clusters: \n");
                        printf("%lu, \t",num);
                        }
                }
        }
        break;

        case MTR_NO_OBTUVO_INFO_ARCH: //termino de obtener la info del archivo
        {
        	char * nombreArchivo = NULL;
            char motivo;
            
                mtf_obtener_datos(centro_consola, datosMensaje.codigo, (char **) &nombreArchivo,(char *) &motivo);

            if (motivo == 1) {
                printf("Archivo no existe %s \n", nombreArchivo);
                
            } else
                printf("Archivo esta vacio %s \n", nombreArchivo);
                
            free(nombreArchivo);
        }
        break;

        case MTQ_CERRAR_CONSOLA_FUSE:
        {

            exit(1);
        }
        break;

        default: //si me llega cualquier cosa lo mando de vuelta

            mtf_enviar_mensaje(centro_consola, datosMensaje.remitente, MTQ_MENSAJE_NO_VALIDO);

        break;
        }
    break;
    }
}

//funcion que descarta las lineas nuevas
void ___descartar_linea_consola (void) {

    char dato;

    dato = getchar();

    while (dato != '\n');
}

void ___cambiar_tamano (void ** vectorCadenas,unsigned int tamano, unsigned int cantidad) {

  if (cantidad == 0) {
    free(* vectorCadenas);
    * vectorCadenas = NULL;
    return;
  }
  if (* vectorCadenas == NULL) {
    * vectorCadenas = malloc(tamano * cantidad);
    return;
  }
  * vectorCadenas = realloc(* vectorCadenas, tamano * cantidad);
}

#endif
